package com.nami.ucenter.infra.acl.repository.user;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nami.ucenter.domain.model.UserModel;
import com.nami.ucenter.domain.port.repository.UserRepository;
import com.nami.ucenter.infra.core.cache.UserCache;
import com.nami.ucenter.infra.acl.repository.user.convertor.UserConvert;
import com.nami.ucenter.infra.core.mybatis.mapper.user.UserMapper;
import com.nami.ucenter.infra.core.mybatis.dataobject.UserDO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.BatchResult;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * im用户信息 服务实现类
 * </p>
 *
 * @author lbc
 * @since 2023-07-19
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepository {

    private final UserMapper userMapper;

    @Override
    public List<UserModel> listByUserIds(List<String> userIds) {
        TimeInterval timer = DateUtil.timer();

        if (CollUtil.isEmpty(userIds)) {
            return null;
        }
        log.info("[user-list] 批量获取用户信息，size={}", userIds.size());
        List<UserModel> result = new ArrayList<>();
        List<String> qryIds = new ArrayList<>();
        for (String userId : userIds) {
            UserModel model = UserCache.get(userId);
            if (model != null) {
                result.add(model);
                continue;
            }
            qryIds.add(userId);
        }

        if (CollUtil.isNotEmpty(qryIds)) {
            List<UserDO> list = userMapper.selectList(new LambdaQueryWrapper<UserDO>().in(UserDO::getUserId, userIds));
            if (CollUtil.isEmpty(list)) {
                return result;
            }
            List<UserModel> userModels = UserConvert.INSTANCE.convertList(list);
            if (CollUtil.isNotEmpty(userModels)) {
                for (UserModel userModel : userModels) {
                    UserCache.add(userModel.getUserId(), userModel);
                }
                result.addAll(userModels);
            }
        }

        if (timer.interval() > 100) {
            log.warn("[user-list] 获取用户信息出现慢查询，size={} use={}ms",
                userIds.size(), timer.interval());
        }
        return result;
    }

    @Override
    public Map<String, UserModel> getUsers(List<String> userIds) {
        TimeInterval timer = DateUtil.timer();
        if (CollUtil.isEmpty(userIds)) {
            return new HashMap<>();
        }
        List<UserModel> users = this.listByUserIds(userIds);
        if (CollUtil.isEmpty(users)) {
            return new HashMap<>();
        }
        Map<String, UserModel> result = users.stream()
            .collect(Collectors.toMap(UserModel::getUserId, Function.identity()));
        if (timer.interval() > 100) {
            log.warn("[user-db] 获取用户耗时高，size={}，use={}ms", users.size(), timer.interval());
        }
        return result;
    }

    @Override
    public UserModel getUserByUserId(String userId) {
        if (StringUtils.isBlank(userId)) {
            return null;
        }

        UserModel model = UserCache.get(userId);
        if (model != null) {
            return model;
        }

        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId));
        if (null == user) {
            return null;
        }
        UserModel result = UserConvert.INSTANCE.convert(user);
        UserCache.add(userId, result);
        return result.clone();
    }

    @Override
    public UserModel find(String appKey, String userId) {
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(userId)) {
           throw new IllegalArgumentException("参数丢失！");
        }
        UserModel model = UserCache.get(userId);
        if (model != null) {
            return model;
        }
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
            .eq(UserDO::getAppKey, appKey)
            .eq(UserDO::getUserId, userId));
        UserModel result = UserConvert.INSTANCE.convert(user);
        UserCache.add(userId, result);
        return result.clone();
    }

    @Override
    public UserModel getUserByAccount(String account) {
        if (StringUtils.isBlank(account)) {
            return null;
        }
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getAccount, account));
        return UserConvert.INSTANCE.convert(user);
    }

    @Override
    public boolean add(UserModel user) {
        UserDO convert = UserConvert.INSTANCE.convert(user);
        convert.setGmtCreate(new Date());
        convert.setGmtModified(new Date());
        convert.setDelFlag("0");
        log.info("[user-save] save user:{}", JsonUtils.toJsonString(convert));
        userMapper.insert(convert);
        return Boolean.TRUE;
    }

    @Override
    public boolean addALl(List<UserModel> users) {
        List<UserDO> userList = UserConvert.INSTANCE.convertList2(users);
        List<BatchResult> results = userMapper.insert(userList);
        return Boolean.TRUE;
    }

    @Override
    public boolean updUserById(UserModel user) {
        UserDO userDO = UserConvert.INSTANCE.convert(user);
        userMapper.updateById(userDO);
        UserCache.add(user.getUserId(), user);
        return Boolean.TRUE;
    }

    @Override
    public UserModel getUserByMobile(String mobile) {
        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getMobile, mobile));
        if (userDO == null) {
            return null;
        }
        return UserConvert.INSTANCE.convert(userDO);
    }

}
